# Copyright (c) HySoP 2011-2024
#
# This file is part of HySoP software.
# See "https://particle_methods.gricad-pages.univ-grenoble-alpes.fr/hysop-doc/"
# for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import sympy as sm
from hysop.constants import HYSOP_REAL
from hysop.tools.htypes import check_instance
from hysop.parameters.tensor_parameter import TensorParameter, Parameter
[docs]
class BufferParameter(Parameter):
"""
A buffer parameter is np.ndarray with specific shape and dtype.
A parameter is a value that may change as simulation advances.
"""
def __new__(
cls, shape=None, dtype=HYSOP_REAL, initial_value=None, symbol=None, **kwds
):
parameter_types = (np.ndarray,)
initial_value = TensorParameter._compute_initial_value(
shape=shape, dtype=dtype, initial_value=initial_value
)
obj = super().__new__(
cls, parameter_types=parameter_types, initial_value=initial_value, **kwds
)
obj._symbol = None
obj._update_symbol(symbol)
return obj
def __init__(
selff, shape=None, dtype=HYSOP_REAL, initial_value=None, symbol=None, **kwds
):
parameter_types = (np.ndarray,)
initial_value = TensorParameter._compute_initial_value(
shape=shape, dtype=dtype, initial_value=initial_value
)
obj = super().__init__(
parameter_types=parameter_types, initial_value=initial_value, **kwds
)
[docs]
def reallocate_buffer(self, shape, dtype, initial_value=None, symbol=None):
self._value = TensorParameter._compute_initial_value(
shape, dtype, initial_value
)
self._update_symbol(symbol)
def _update_symbol(self, symbol=None):
from hysop.symbolic.array import HostSymbolicBuffer
if symbol:
check_instance(symbol, HostSymbolicBuffer)
symbol.bind_memory_selfect(memory_selfect=self._value, force=True)
self._symbol = symbol
elif self._symbol is None:
self._symbol = HostSymbolicBuffer(
memory_object=self._value,
name=self.var_name,
pretty_name=self.pretty_name,
var_name=self.var_name,
)
else:
self._symbol.bind_memory_object(memory_object=self._value, force=True)
[docs]
def long_description(self):
ss = """\
BufferParameter[name={}]
*shape: {}
*dtype: {}
""".format(
self.name, self.shape, self.dtype
)
return ss
[docs]
def short_description(self):
attrs = ("name", "shape", "dtype")
info = []
for attr in attrs:
val = getattr(self, attr)
if val is not None:
info.append(f"{attr}={val}")
attrs = ", ".join(info)
ss = "BufferParameter[{}]"
ss = ss.format(attrs)
return ss
def _get_value_impl(self):
"""Return a read-only reference on the underlying data buffer."""
assert self._value is not None
view = self._value.view()
view.flags.writeable = False
return view.view()
def _set_value_impl(self, value):
"""Given value will be copied into internal buffer."""
assert self._value is not None
assert (value is not None) and isinstance(value, np.ndarray)
if value.shape != self.shape:
msg = "Parameter shape mismatch, expected {} but got {}."
msg = msg.format(self.shape, value.shape)
raise ValueError(msg)
if value.dtype != self.dtype:
msg = "Parameter dtype mismatch, expected {} but got {}."
msg = msg.format(self.dtype, value.dtype)
raise ValueError(msg)
self._value[...] = value
[docs]
def iterviews(self):
"""Iterate over all parameters views to yield scalarparameters."""
yield (None, self)
def _get_shape(self):
"""Get parameter shape."""
return self._value.shape if (self._value is not None) else None
def _get_ndim(self):
"""Get parameter ndim."""
return self._value.ndim if (self._value is not None) else None
def _get_size(self):
"""Get parameter size."""
return self._value.size if (self._value is not None) else 0
def _get_dtype(self):
"""Get parameter dtype."""
return self._value.dtype if (self._value is not None) else None
def _get_ctype(self):
"""Get the data type of the discrete field as a C type."""
from hysop.backend.device.codegen.base.variables import dtype_to_ctype
dtype = self.dtype
return dtype_to_ctype(dtype)
ndim = property(_get_ndim)
shape = property(_get_shape)
size = property(_get_size)
dtype = property(_get_dtype)
ctype = property(_get_ctype)